﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;

namespace DungeonAdventure.ErrorHandler
{
    public sealed class Logging
    {
        #region Privates

        private static volatile Logging _instance;
        private static readonly object SyncRoot = new object();

        private readonly string _logFilename;
        private FileStream _logFs;
        private StreamWriter _logSw;
        private bool _isAvailable = false;
        

        #endregion

        #region Properties

        public static Logging Instance
        {
            get
            {
                if (_instance == null)
                {
                    lock(SyncRoot)
                    {
                        if(_instance == null)
                        {
                            _instance = new Logging();
                        }
                    }
                }

                return _instance;
            }
        }

        #endregion

        #region Ctor

        private Logging()
        {
            _logFilename = Assembly.GetEntryAssembly().Location.Replace(".exe", ".log");
            try
            {
                
                _logFs = new FileStream(_logFilename, FileMode.Create, FileAccess.Write, FileShare.Read);
                _logSw = new StreamWriter(_logFs);
                //Info("Starting Dungeon Adventure");
                _isAvailable = true;
            }
            catch
            {
                _isAvailable = false;
            }
        }

        #endregion

        #region Functions

        public void Info(string message)
        {
            var data = new Dictionary<string, string>
                           {
                               {"Level", "Info"},
                               {"Message", message}
                           };

            Write(data);
        }

        public void Warning(string message)
        {
            var data = new Dictionary<string, string>
                           {
                               {"Level", "Warning"},
                               {"Message", message}
                           };

            Write(data); 
        }

        public void Error(string message)
        {
            var data = new Dictionary<string, string>
                           {
                               {"Level", "Error"},
                               {"Message", message}
                           };

            Write(data);
        }

        public void Fatal(string message)
        {
            var data = new Dictionary<string, string>
                           {
                               {"Level", "Fatal"},
                               {"Message", message}
                           };

            Write(data);
        }

        public void Debug(string message)
        {
            var data = new Dictionary<string, string>
                           {
                               {"Level", "Debug"},
                               {"Message", message}
                           };

            Write(data);
        }

        public void Exception(Exception exception)
        {
            /*
            var data = new Dictionary<string, string>
                           {
                               {"Level", "Warning"},
                               {"DateTime", DateTime.UtcNow.ToString()},
                               {"Message", message}
                           };

            Write(data);
            */
        }

        private void Write(Dictionary<string, string> data)
        {
            try
            {
                if (_isAvailable)
                {
                    if (data.Count() > 0)
                    {
                        if (_logFs.CanWrite)
                        {                            
                            foreach(var d in data)
                            {
                                _logSw.WriteLine(String.Format("{0}:{1}", d.Key, d.Value));
                            }

                            _logFs.Flush();
                            _logFs.Close();
                        }
                    }
                }
            }
            catch
            {
                _isAvailable = false;

                if (_logFs != null)
                {
                    _logFs.Close();
                }
            }
        }

        #endregion
    }
}
